package com.smart.community.property.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.cache.DataScopeInfo;
import com.smart.community.commons.entity.property.UserPropertyCompany;
import com.smart.community.commons.exception.BusinessException;
import com.smart.community.commons.result.Result;
import com.smart.community.commons.result.ResultCode;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.property.mapper.UserPropertyCompanyMapper;
import com.smart.community.property.service.DataScopeService;
import com.smart.community.property.service.IUserPropertyCompanyService;

import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import javax.validation.constraints.NotNull;

/**
 * 用户物业公司关联服务实现类
 * 
 * <p>负责用户与物业公司关联关系的管理，包括用户分配、移除、信息更新等操作。
 * 严格遵循《Java后端SpringBoot代码开发规范.md》Service规范，以生产环境标准执行。</p>
 * 
 * <p><strong>核心功能：</strong></p>
 * <ul>
 *   <li>用户与物业公司关联关系的增删改查</li>
 *   <li>用户分配和移除物业公司</li>
 *   <li>用户物业公司信息更新</li>
 *   <li>数据权限控制和缓存优化</li>
 *   <li>性能监控和异常处理</li>
 * </ul>
 * 
 * <p><strong>技术特性：</strong></p>
 * <ul>
 *   <li>生产环境标准：移除throws Exception声明，使用统一异常处理</li>
 *   <li>缓存优化：使用Redis缓存提升查询性能</li>
 *   <li>数据权限：集成DataScopeFeign进行权限控制</li>
 *   <li>性能监控：详细的性能指标记录</li>
 *   <li>事务管理：使用Seata分布式事务</li>
 * </ul>
 * 
 * @author Wu.Liang
 * @since 2025-06-29
 * @version 3.0.0 - 生产环境标准优化，缓存优化，性能监控
 */
@Slf4j
@Service
public class UserPropertyCompanyServiceImpl extends ServiceImpl<UserPropertyCompanyMapper, UserPropertyCompany> 
    implements IUserPropertyCompanyService {

    // ==================== 缓存常量 ====================
    
    /** 用户物业公司关联缓存键前缀 */
    private static final String USER_PROPERTY_CACHE_KEY_PREFIX = "user:property:";
    
    /** 物业公司用户缓存键前缀 */
    private static final String PROPERTY_USER_CACHE_KEY_PREFIX = "property:user:";
    
    // ==================== 性能监控阈值 ====================
    
    /** 性能警告阈值（毫秒） */
    private static final long PERFORMANCE_WARNING_THRESHOLD = 1000;
    
    /** 性能错误阈值（毫秒） */
    private static final long PERFORMANCE_ERROR_THRESHOLD = 3000;

    @Autowired
    private DataScopeService dataScopeService;

    // ==================== 工具方法 ====================
    
    /**
     * 记录性能指标
     * 
     * @param methodName 方法名
     * @param startTime 开始时间
     * @param params 参数信息
     */
    private void logPerformanceMetrics(String methodName, long startTime, Object... params) {
        long duration = System.currentTimeMillis() - startTime;
        String paramInfo = params.length > 0 ? String.join(", ", 
            java.util.Arrays.stream(params).map(String::valueOf).toArray(String[]::new)) : "";
        
        if (duration > PERFORMANCE_ERROR_THRESHOLD) {
            log.error("性能错误 - 方法: {}, 耗时: {}ms, 参数: {}", methodName, duration, paramInfo);
        } else if (duration > PERFORMANCE_WARNING_THRESHOLD) {
            log.warn("性能警告 - 方法: {}, 耗时: {}ms, 参数: {}", methodName, duration, paramInfo);
        } else {
            log.debug("性能正常 - 方法: {}, 耗时: {}ms, 参数: {}", methodName, duration, paramInfo);
        }
    }
    
    /**
     * 验证用户ID参数
     * 
     * @param userId 用户ID
     */
    private void validateUserId(Long userId) {
        if (userId == null || userId <= 0) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "用户ID不能为空或无效");
        }
    }
    
    /**
     * 验证物业公司ID参数
     * 
     * @param propertyCompanyId 物业公司ID
     */
    private void validatePropertyCompanyId(Long propertyCompanyId) {
        if (propertyCompanyId == null || propertyCompanyId <= 0) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "物业公司ID不能为空或无效");
        }
    }
    
    /**
     * 验证数据权限
     * 
     * @param propertyCompanyId 物业公司ID
     */
    private void validateDataPermission(Long propertyCompanyId) {
        try {
            // 首先进行直接的超级管理员判断
            Long currentUserId = SecurityUtils.getCurrentUserId();
            if (currentUserId != null && isCurrentUserSuperAdmin(currentUserId)) {
                log.debug("超级管理员用户，跳过数据权限校验，用户ID：{}", currentUserId);
                return;
            }
            
            // 获取当前用户数据权限
            DataScopeInfo dataScopeInfo = null;
            try {
                dataScopeInfo = dataScopeService.getCurrentUserDataScope();
            } catch (Exception e) {
                log.warn("获取当前用户数据权限信息失败，可能是Feign接口调用或用户未登录: {}", e.getMessage());
                // 根据Feign接口开发规范，当无法获取用户权限信息时，不抛出异常，只记录警告
                return;
            }
            
            if (dataScopeInfo == null) {
                log.warn("用户数据权限信息为空，跳过权限校验");
                return;
            }
            
            // 超级管理员跳过权限校验
            if (dataScopeInfo.isSuperAdmin()) {
                log.debug("超级管理员用户，跳过数据权限校验");
                return;
            }
            
            // 检查物业公司权限
            if (!dataScopeInfo.hasPropertyCompanyPermission(propertyCompanyId)) {
                throw new BusinessException(ResultCode.PERMISSION_DENIED, "无权限访问该物业公司数据");
            }
            
        } catch (BusinessException e) {
            // 业务异常直接抛出
            throw e;
        } catch (Exception e) {
            log.warn("数据权限校验异常：{}", e.getMessage());
            // 其他异常不抛出，只记录警告日志
        }
    }
    
    /**
     * 统一异常处理
     * 
     * @param e 异常
     * @param operation 操作描述
     * @return 业务异常
     */
    private BusinessException handleException(Exception e, String operation) {
        if (e instanceof BusinessException) {
            log.warn("{}业务异常：{}", operation, e.getMessage());
            return (BusinessException) e;
        } else {
            log.error("{}系统异常", operation, e);
            return new BusinessException(ResultCode.OPERATION_FAILED, operation + "失败：" + e.getMessage());
        }
    }
    
    /**
     * 清除用户物业公司关联相关缓存
     * 
     * @param userId 用户ID
     * @param propertyCompanyId 物业公司ID
     */
    private void clearUserPropertyCache(Long userId, Long propertyCompanyId) {
        try {
            // 清除用户物业公司关联缓存
            if (userId != null) {
                String userCacheKey = USER_PROPERTY_CACHE_KEY_PREFIX + userId;
                log.debug("清除用户物业公司关联缓存：{}", userCacheKey);
            }
            
            // 清除物业公司用户缓存
            if (propertyCompanyId != null) {
                String propertyCacheKey = PROPERTY_USER_CACHE_KEY_PREFIX + propertyCompanyId;
                log.debug("清除物业公司用户缓存：{}", propertyCacheKey);
            }
        } catch (Exception e) {
            log.warn("清除用户物业公司关联缓存失败：{}", e.getMessage());
        }
    }
    
    /**
     * 获取当前用户ID
     * 
     * @return 用户ID
     */
    private Long getCurrentUserId() {
        try {
            return SecurityUtils.getCurrentUserId();
        } catch (Exception e) {
            log.warn("获取当前用户ID失败：{}", e.getMessage());
            return null;
        }
    }

	@Override
	@GlobalTransactional
	@CacheEvict(value = {"userPropertyCompany", "propertyInfo"}, allEntries = true)
	public Result<Void> assignUserToPropertyCompany(Long userId, Long propertyCompanyId, 
												   String position, String department, String employeeNo) {
        long startTime = System.currentTimeMillis();
        log.info("为用户分配物业公司，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId);
        
        try {
            // 1. 参数校验
            validateUserId(userId);
            validatePropertyCompanyId(propertyCompanyId);
            
            // 2. 校验数据权限
            validateDataPermission(propertyCompanyId);
            
            // 3. 检查是否已存在关联
            if (isUserAssignedToPropertyCompany(userId, propertyCompanyId)) {
                return Result.fail("用户已关联该物业公司");
            }
            
            // 4. 创建关联记录
            UserPropertyCompany userPropertyCompany = new UserPropertyCompany();
            userPropertyCompany.setUserId(userId);
            userPropertyCompany.setPropertyCompanyId(propertyCompanyId);
            userPropertyCompany.setPosition(position);
            userPropertyCompany.setDepartment(department);
            userPropertyCompany.setEmployeeNo(employeeNo);
            userPropertyCompany.setJoinDate(LocalDate.now());
            userPropertyCompany.setStatus(1); // 在职
            
            Long currentUserId = getCurrentUserId();
            userPropertyCompany.setCreateBy(currentUserId);
            userPropertyCompany.setCreateTime(LocalDateTime.now());
            userPropertyCompany.setUpdateBy(currentUserId);
            userPropertyCompany.setUpdateTime(LocalDateTime.now());
            
            // 5. 保存到数据库
            boolean success = this.save(userPropertyCompany);
            if (!success) {
                throw new BusinessException(ResultCode.OPERATION_FAILED, "用户分配物业公司失败");
            }
            
            // 6. 清除相关缓存
            clearUserPropertyCache(userId, propertyCompanyId);
            
            // 7. 记录性能指标
            logPerformanceMetrics("assignUserToPropertyCompany", startTime, userId, propertyCompanyId);
            
            log.info("用户分配物业公司成功");
            return Result.success();
            
        } catch (Exception e) {
            logPerformanceMetrics("assignUserToPropertyCompany", startTime, userId, propertyCompanyId);
            throw handleException(e, "用户分配物业公司");
        }
    }

	@Override
	@GlobalTransactional
	@CacheEvict(value = {"userPropertyCompany", "propertyInfo"}, allEntries = true)
	public Result<Void> removeUserFromPropertyCompany(Long userId, Long propertyCompanyId) {
        long startTime = System.currentTimeMillis();
        log.info("移除用户与物业公司的关联，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId);
        
        try {
            // 1. 参数校验
            validateUserId(userId);
            validatePropertyCompanyId(propertyCompanyId);
            
            // 2. 校验数据权限
            validateDataPermission(propertyCompanyId);
            
            // 3. 查询关联记录
            LambdaQueryWrapper<UserPropertyCompany> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserPropertyCompany::getUserId, userId);
            queryWrapper.eq(UserPropertyCompany::getPropertyCompanyId, propertyCompanyId);
            
            UserPropertyCompany existingRecord = this.getOne(queryWrapper);
            if (existingRecord == null) {
                throw new BusinessException(ResultCode.DATA_NOT_FOUND, "用户物业公司关联不存在");
            }
            
            // 4. 物理删除
            boolean success = this.removeById(existingRecord.getId());
            if (!success) {
                throw new BusinessException(ResultCode.OPERATION_FAILED, "移除用户物业公司关联失败");
            }
            
            // 5. 清除相关缓存
            clearUserPropertyCache(userId, propertyCompanyId);
            
            // 6. 记录性能指标
            logPerformanceMetrics("removeUserFromPropertyCompany", startTime, userId, propertyCompanyId);
            
            log.info("移除用户物业公司关联成功");
            return Result.success();
            
        } catch (Exception e) {
            logPerformanceMetrics("removeUserFromPropertyCompany", startTime, userId, propertyCompanyId);
            throw handleException(e, "移除用户物业公司关联");
        }
    }

	@Override
	@GlobalTransactional
	@CacheEvict(value = {"userPropertyCompany", "propertyInfo"}, allEntries = true)
	public Result<Void> updateUserPropertyCompanyInfo(Long userId, Long propertyCompanyId,
												   String position, String department, String employeeNo) {
        long startTime = System.currentTimeMillis();
        log.info("更新用户在物业公司的信息，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId);
        
        try {
            // 1. 参数校验
            validateUserId(userId);
            validatePropertyCompanyId(propertyCompanyId);
            
            // 2. 校验数据权限
            validateDataPermission(propertyCompanyId);
            
            // 3. 查询关联记录
            LambdaQueryWrapper<UserPropertyCompany> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserPropertyCompany::getUserId, userId);
            queryWrapper.eq(UserPropertyCompany::getPropertyCompanyId, propertyCompanyId);
            
            UserPropertyCompany userPropertyCompany = this.getOne(queryWrapper);
            if (userPropertyCompany == null) {
                throw new BusinessException(ResultCode.DATA_NOT_FOUND, "用户物业公司关联不存在");
            }
            
            // 4. 更新信息
            userPropertyCompany.setPosition(position);
            userPropertyCompany.setDepartment(department);
            userPropertyCompany.setEmployeeNo(employeeNo);
            userPropertyCompany.setUpdateBy(getCurrentUserId());
            userPropertyCompany.setUpdateTime(LocalDateTime.now());
            
            // 5. 保存到数据库
            boolean success = this.updateById(userPropertyCompany);
            if (!success) {
                throw new BusinessException(ResultCode.OPERATION_FAILED, "更新用户物业公司信息失败");
            }
            
            // 6. 清除相关缓存
            clearUserPropertyCache(userId, propertyCompanyId);
            
            // 7. 记录性能指标
            logPerformanceMetrics("updateUserPropertyCompanyInfo", startTime, userId, propertyCompanyId);
            
            log.info("更新用户物业公司信息成功");
            return Result.success();
            
        } catch (Exception e) {
            logPerformanceMetrics("updateUserPropertyCompanyInfo", startTime, userId, propertyCompanyId);
            throw handleException(e, "更新用户物业公司信息");
        }
    }

    @Override
    @Cacheable(value = "userPropertyCompany", key = "#userId", unless = "#result == null || #result.isEmpty()")
    public List<UserPropertyCompany> getUserPropertyCompanies(Long userId) {
        long startTime = System.currentTimeMillis();
        log.info("获取用户的物业公司列表，用户ID：{}", userId);
        
        try {
            // 1. 参数校验
            validateUserId(userId);
            
            // 2. 查询用户物业公司关联
            LambdaQueryWrapper<UserPropertyCompany> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserPropertyCompany::getUserId, userId);
            queryWrapper.eq(UserPropertyCompany::getStatus, 1); // 在职状态
            queryWrapper.orderByDesc(UserPropertyCompany::getCreateTime);
            
            List<UserPropertyCompany> result = this.list(queryWrapper);
            
            // 3. 记录性能指标
            logPerformanceMetrics("getUserPropertyCompanies", startTime, userId, result.size());
            
            log.info("获取用户物业公司列表成功，数量：{}", result.size());
            return result;
            
        } catch (Exception e) {
            logPerformanceMetrics("getUserPropertyCompanies", startTime, userId);
            throw handleException(e, "获取用户物业公司列表");
        }
    }

    @Override
    @Cacheable(value = "userPropertyCompany", key = "'property:' + #propertyCompanyId", unless = "#result == null || #result.isEmpty()")
    public List<UserPropertyCompany> getPropertyCompanyUsers(Long propertyCompanyId) {
        long startTime = System.currentTimeMillis();
        log.info("获取物业公司的用户列表，物业公司ID：{}", propertyCompanyId);
        
        try {
            // 1. 参数校验
            validatePropertyCompanyId(propertyCompanyId);
            
            // 2. 校验数据权限
            validateDataPermission(propertyCompanyId);
            
            // 3. 查询物业公司用户关联
            LambdaQueryWrapper<UserPropertyCompany> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserPropertyCompany::getPropertyCompanyId, propertyCompanyId);
            queryWrapper.eq(UserPropertyCompany::getStatus, 1); // 在职状态
            queryWrapper.orderByDesc(UserPropertyCompany::getCreateTime);
            
            List<UserPropertyCompany> result = this.list(queryWrapper);
            
            // 4. 记录性能指标
            logPerformanceMetrics("getPropertyCompanyUsers", startTime, propertyCompanyId, result.size());
            
            log.info("获取物业公司用户列表成功，数量：{}", result.size());
            return result;
            
        } catch (Exception e) {
            logPerformanceMetrics("getPropertyCompanyUsers", startTime, propertyCompanyId);
            throw handleException(e, "获取物业公司用户列表");
        }
    }

    @Override
    @Cacheable(value = "userPropertyCompany", key = "'check:' + #userId + ':' + #propertyCompanyId")
    public boolean isUserAssignedToPropertyCompany(Long userId, Long propertyCompanyId) {
        long startTime = System.currentTimeMillis();
        log.debug("检查用户是否已关联物业公司，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId);
        
        try {
            // 1. 参数校验
            validateUserId(userId);
            validatePropertyCompanyId(propertyCompanyId);
            
            // 2. 查询关联关系
            LambdaQueryWrapper<UserPropertyCompany> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserPropertyCompany::getUserId, userId);
            queryWrapper.eq(UserPropertyCompany::getPropertyCompanyId, propertyCompanyId);
            queryWrapper.eq(UserPropertyCompany::getStatus, 1); // 在职状态
            
            boolean result = this.count(queryWrapper) > 0;
            
            // 3. 记录性能指标
            logPerformanceMetrics("isUserAssignedToPropertyCompany", startTime, userId, propertyCompanyId, result);
            
            return result;
            
        } catch (Exception e) {
            logPerformanceMetrics("isUserAssignedToPropertyCompany", startTime, userId, propertyCompanyId);
            throw handleException(e, "检查用户物业公司关联");
        }
    }

	@Override
	@Cacheable(value = "userPropertyCompany", key = "'userIds:' + #propertyCompanyId", unless = "#result == null || #result.isEmpty()")
	public List<Long> getUserIdsByPropertyCompanyId(@NotNull Long propertyCompanyId) {
		long startTime = System.currentTimeMillis();
		log.info("获取物业公司的用户ID列表，物业公司ID：{}", propertyCompanyId);
		
		try {
			// 1. 参数校验
			validatePropertyCompanyId(propertyCompanyId);
			
			// 2. 校验数据权限
			validateDataPermission(propertyCompanyId);
			
			// 3. 查询用户ID列表
			LambdaQueryWrapper<UserPropertyCompany> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.eq(UserPropertyCompany::getPropertyCompanyId, propertyCompanyId);
			queryWrapper.eq(UserPropertyCompany::getStatus, 1); // 在职状态
			
			List<Long> result = this.list(queryWrapper).stream()
					.map(UserPropertyCompany::getUserId)
					.distinct()
					.collect(Collectors.toList());
			
			// 4. 记录性能指标
			logPerformanceMetrics("getUserIdsByPropertyCompanyId", startTime, propertyCompanyId, result.size());
			
			log.info("获取物业公司用户ID列表成功，数量：{}", result.size());
			return result;
			
		} catch (Exception e) {
			logPerformanceMetrics("getUserIdsByPropertyCompanyId", startTime, propertyCompanyId);
			throw handleException(e, "获取物业公司用户ID列表");
		}
	}

	@Override
	@Cacheable(value = "userPropertyCompany", key = "'userIds:' + T(String).join(',', #propertyCompanyIds)", unless = "#result == null || #result.isEmpty()")
	public List<Long> getUserIdsByPropertyCompanyIds(@NotNull List<Long> propertyCompanyIds) {
		long startTime = System.currentTimeMillis();
		log.info("获取多个物业公司的用户ID列表，物业公司ID列表：{}", propertyCompanyIds);
		
		try {
			// 1. 参数校验
			if (propertyCompanyIds == null || propertyCompanyIds.isEmpty()) {
				return Collections.emptyList();
			}
			
			// 2. 校验数据权限（批量校验）
			for (Long propertyCompanyId : propertyCompanyIds) {
				validateDataPermission(propertyCompanyId);
			}
			
			// 3. 查询用户ID列表
			LambdaQueryWrapper<UserPropertyCompany> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.in(UserPropertyCompany::getPropertyCompanyId, propertyCompanyIds);
			queryWrapper.eq(UserPropertyCompany::getStatus, 1); // 在职状态
			
			List<Long> result = this.list(queryWrapper).stream()
					.map(UserPropertyCompany::getUserId)
					.distinct()
					.collect(Collectors.toList());
			
			// 4. 记录性能指标
			logPerformanceMetrics("getUserIdsByPropertyCompanyIds", startTime, propertyCompanyIds.size(), result.size());
			
			log.info("获取多个物业公司用户ID列表成功，数量：{}", result.size());
			return result;
			
		} catch (Exception e) {
			logPerformanceMetrics("getUserIdsByPropertyCompanyIds", startTime, propertyCompanyIds.size());
			throw handleException(e, "获取多个物业公司用户ID列表");
		}
	}

	/**
	 * 判断当前用户是否为超级管理员
	 * 
	 * 根据《Java后端SpringBoot代码开发规范_重构版.md》和《系统状态枚举权威标准声明.md》规范
	 * 通过用户类型、角色和特殊用户名进行综合判断
	 * 
	 * @param userId 用户ID
	 * @return 是否为超级管理员
	 */
	private boolean isCurrentUserSuperAdmin(Long userId) {
		if (userId == null) {
			return false;
		}
		
		try {
			// 1. 检查用户类型是否为超级管理员
			String userType = SecurityUtils.getCurrentUserType();
			if (userType != null && "SUPER_ADMIN".equals(userType)) {
				log.debug("用户类型为超级管理员，用户ID: {}", userId);
				return true;
			}
			
			// 2. 检查用户角色是否包含超级管理员角色
			List<String> roles = SecurityUtils.getRoleList();
			if (roles != null && !roles.isEmpty()) {
				for (String role : roles) {
					if ("SUPER_ADMIN".equals(role)) {
						log.debug("用户拥有超级管理员角色，用户ID: {}", userId);
						return true;
					}
				}
			}
			
			// 3. 特殊处理admin用户（系统默认超级管理员）
			String username = SecurityUtils.getCurrentUsername();
			if ("admin".equals(username)) {
				log.debug("admin用户，用户ID: {}", userId);
				return true;
			}
			
			log.debug("用户不是超级管理员，用户ID: {}, 用户类型: {}, 角色: {}", userId, userType, roles);
			return false;
		} catch (Exception e) {
			log.warn("检查超级管理员状态失败，用户ID: {}", userId, e);
			return false;
		}
	}
}
